use std::collections::{hash_map::Entry, BTreeSet, HashMap, HashSet};

use serde::{Deserialize, Serialize};
use wtask_base::{cmd::{file_de_load, file_en_save}, error::{WError, WResult}, export::KillSender};

use crate::handle::flow::{basic::{FlowData, FlowRunLog, FlowStatus, FlowStatusResult}, timer::FlowApp};




pub(super) trait FlowStorageDataTrait {
    fn get_has_id(&self) -> &str;
}


#[derive(Debug, Serialize, Deserialize)]
pub(super) struct FlowStorageData<T> {
    pub(super) data: HashMap<String, T>,
    pub(super) has: HashMap<String, BTreeSet<String>>,
}


impl<T: FlowStorageDataTrait> FlowStorageData<T> {
    pub(super) fn remove(&mut self, key: &str) -> Option<T> {
        self.data.remove(key).inspect(| r | {
            if let Some(v) = self.has.get_mut(r.get_has_id()) {
                v.remove(key);
            }
        })
    }

    pub(super) fn insert(&mut self, key: String, data: T) {
        let has_id = data.get_has_id().to_string();
        let key_clone = key.clone();
        self.data.insert(key, data);
        match self.has.entry(has_id) {
            Entry::Occupied(mut v) => v.get_mut().insert(key_clone),
            Entry::Vacant(v) => v.insert(BTreeSet::new()).insert(key_clone),
        };
    }
}


impl<T: FlowStorageDataTrait> Default for FlowStorageData<T> {
    fn default() -> Self {
        Self {
            data: HashMap::new(),
            has: HashMap::new()
        }
    }
}


impl FlowStorageDataTrait for FlowRunLog {
    fn get_has_id(&self) -> &str {
        &self.data.setting.id
    }
}

type FlowTimerStorage = (FlowApp, Vec<String>);
impl FlowStorageDataTrait for FlowTimerStorage {
    fn get_has_id(&self) -> &str {
        &self.0.data.setting.id
    }
}


#[derive(Debug, Serialize, Deserialize)]
pub(crate) struct FlowStorage {
    // flow的数据
    pub(super) storage: HashMap<String, FlowData>,
    // 权限群组有哪些flow: group_id -> { flow_id }
    pub(super) groups: HashMap<String, HashSet<String>>,
    // 正在运行的flow timer记录
    // timer_id -> ( app, [run_id] )
    // flow-id -> { timer_id }
    #[serde(skip)]
    pub(super) timer: FlowStorageData<FlowTimerStorage>,
    // 运行的flow记录: run-id -> flow_log
    // flow运行的记录： flow_id -> { run-id }
    #[serde(skip)]
    pub(super) run: FlowStorageData<FlowRunLog>,
    // 正在运行flow的killer: run-id -> killer
    #[serde(skip)]
    pub(super) kill: HashMap<String, KillSender<bool>>,
}


/// 供接口查询使用
impl FlowStorage {
    pub(super) fn data_get(&self, flow_id: &str) -> WResult<&FlowData> {
        self.storage
            .get(flow_id)
            .ok_or(WError::DataError("storage get error".to_owned()))
    }

    pub(super) fn log_list(&self, flow_id: &str) -> Vec<&FlowStatusResult> {
        if let Some(r) = self.run.has.get(flow_id) {
            r.iter()
                .filter_map(| v | self.run.data.get(v).map(| v | &v.status.result))
                .collect::<Vec<_>>()
        } else {
            Vec::with_capacity(0)
        }
    }
    
    pub(super) fn group_get(&self, group_id: &str) -> Vec<&str> {
        self.groups
            .get(group_id)
            .map_or(
                Vec::with_capacity(0),
                | v | v.iter().map(| v | v.as_str()).collect::<Vec<&str>>()
            )
    }

    pub(super) fn status_save(&mut self, status: &FlowStatus) -> WResult<()> {
        self.run.data
            .get_mut(&status.result.run_id)
            .ok_or(WError::Empty)?
            .status = status.clone();
        Ok(())
    }
    
    pub(crate) fn drop_data(&mut self) {
        // 关闭正在运行任务
        for killer in self.kill.values() {
            let _ = killer.send(true);
        }
        self.kill.clear();
        // 关闭正在running的
        let log_data = vec!["Shutting, force close ...".to_owned()];
        for log_single in self.run.data.values_mut() {
            if !log_single.status.result.running() {
                continue;
            }
            log_single.done(false, log_data.clone());
        }
        // 持久化
        let _ = file_en_save("flow.timer", &self.timer, None);
        let _ = file_en_save("flow.log", &self.run, None);
        let _ = file_en_save("flow.data", &(&self.storage, &self.groups), None);
    }
}

impl Default for FlowStorage {
    fn default() -> Self {
        let (storage, groups): (HashMap<String, FlowData>, HashMap<String, HashSet<String>>) = file_de_load("flow.data", None, true).unwrap_or_default();
        let run: FlowStorageData<FlowRunLog> = file_de_load("flow.log", None, true).unwrap_or_default();
        let timer: FlowStorageData<(FlowApp, Vec<String>)> = file_de_load("flow.timer", None, true).unwrap_or_default();

        Self {
            storage,
            groups,
            timer,
            run,
            kill: HashMap::new(),
        }
    }
}

